home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 16
/
Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso
/
Aminet
/
dev
/
src
/
wangisrc.lha
/
wangi
/
z
/
GMulti
/
SFPatch.h
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-07
|
3KB
|
151 lines
#ifndef SFPATCH_H
#define SFPATCH_H
/*
* SFPatch.h 1.0
*
* Lee Kindness
*
* Public Domain
*
*/
/* Includes */
#include <exec/types.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
/* Structures */
enum {
JMPINSTR = 0x4ef9
};
typedef struct JmpEntry {
UWORD Instr;
APTR Func;
} JmpEntry;
typedef struct SetFunc {
APTR sf_Func;
APTR sf_OriginalFunc;
JmpEntry *sf_Jmp;
struct Library *sf_Library;
LONG sf_Offset;
LONG sf_QuitMethod;
LONG sf_Count;
} SetFunc;
/* Constants for SetFunc->sf_QuitMethod */
#define SFQ_WAIT 0 /* wait sf_Count seconds (defaults to 3) */
#define SFQ_COUNT 1 /* only quit if count == 0 (retry every 3 secs...) */
/* Prototypes */
BOOL SFReplace(SetFunc *sf);
void SFRestore(SetFunc *sf);
/* The functions... */
/*
* The main method for replacing an Amiga OS function as safe as
* possible is to place the function with a jump table that is
* allocated. While the function is replaced, the jump table simply
* jumps to my routine:
*
* jmp _new_Function
*
* When the user asks the program to quit, we can't simply put the
* pointer back that SetFunction() gives us since someone else might
* have replaced the function. So, we first see if the pointer we
* get back points to the out jump table. If so, then we _can_ put
* the pointer back like normal (no one has replaced the function
* while we has it replaced). But if the pointer isn't mine, then
* we have to replace the jump table function pointer to the old
* function pointer:
*
* jmp _old_Function
*
* Finally, we only deallocate the jump table _if_ we did not have
* to change the jump table.
*/
BOOL SFReplace(SetFunc *sf)
{
BOOL ret;
ret = FALSE;
/* Allocate the jump table */
if (sf->sf_Jmp = AllocVec(sizeof(JmpEntry), MEMF_CLEAR)) {
Forbid();
/* Replace the function with pointer to jump table */
sf->sf_OriginalFunc = SetFunction(sf->sf_Library, sf->sf_Offset, (APTR)sf->sf_Jmp);
/* Setup the jump table */
sf->sf_Jmp->Instr = JMPINSTR;
sf->sf_Jmp->Func = sf->sf_Func;
// Clear the cpu's cache so the execution cache is valid
CacheClearU();
Permit();
/* muck around with the quit stuff... */
if (sf->sf_QuitMethod == SFQ_WAIT) {
if (sf->sf_Count <= 0)
sf->sf_Count = 3;
} else
sf->sf_Count = 0;
ret = TRUE;
}
return ret;
}
void SFRestore(SetFunc *sf)
{
BOOL my_table;
ULONG (*func)();
Forbid();
/* Put old pointer back and get current pointer at same time */
func = SetFunction(sf->sf_Library, sf->sf_Offset, sf->sf_OriginalFunc);
/* Check to see if the pointer we get back is ours */
if ((JmpEntry *)func != sf->sf_Jmp) {
/* If not, leave jump table in place */
my_table = FALSE;
SetFunction(sf->sf_Library, sf->sf_Offset, func);
sf->sf_Jmp->Func = sf->sf_OriginalFunc;
} else {
/* If so, free the jump table */
my_table = TRUE;
FreeVec(sf->sf_Jmp);
}
/* Clear the cpu's cache so the execution cache is valid */
CacheClearU();
Permit();
/* Let the user know if the jump table couldn't be freed */
if ((!my_table) && (IntuitionBase))
DisplayBeep(NULL);
/* Wait... */
if (sf->sf_QuitMethod == SFQ_WAIT) {
/* Wait n seconds */
Delay(sf->sf_Count * 50);
} else {
/* wait until sf->sf_Count == 0 */
while (sf->sf_Count)
Delay(150);
}
}
#endif /* SFPATCH_H */